#include "MyAStar.h"



void MyAStar::wayfinding(CCPoint& startPos, CCPoint& endPos,vector<CCPoint>& ret, bool isEight){
    
    reset();
    
    if(startPos.y<0|| startPos.y>=col ||
       endPos.y<0|| endPos.y>=col ||
       
       startPos.x<0|| startPos.x>=row ||
       endPos.x<0|| endPos.x>=row
       
       ){
        return ;
    }
     

    
    startNode = &(astarMapArr[startPos.y][startPos.x]);
    endNode = &(astarMapArr[endPos.y][endPos.x]);
    
    
    if ( startNode->type != 0){
        return ;
    };
    if (endNode->type != 0){
        return ;
    };
    
    nowNode = startNode;
    
    openList.push_back(nowNode);
    
    while ( endNode->inList!= 2 &&  openList.size()!=0) {
        nowNode = getMinFNode();
        quitList(nowNode); 
        getAroundNode(nowNode, isEight);
    };
    if (openList.size() == 0){
        return ;
    };
     
    
    AStarNode* last=endNode;
    
	std::list<AStarNode*> lst;
    lst.push_front(last);
    
    while(last->parentNode!=NULL){
        last=last->parentNode;
        lst.push_front(last);
        
    }
    
    std::list<AStarNode*>::iterator v = lst.begin();
    for(;v!=lst.end();++v){
        
        AStarNode* node=*v;
        ret.push_back(ccp(node->x,node->y));
    }
    
    return ;
}


AStarNode* MyAStar::getMinFNode(){
    
    std::list<AStarNode*>::iterator v = openList.begin();
    AStarNode* ret=*v;
    ++v;
    for(;v!=openList.end();++v){
       		if(ret->f>= (*v)->f){
            ret=*v;
        }
        
    } 
    return ret;
}

void MyAStar::quitList(AStarNode* node){
     node->inList = 2;
     std::list<AStarNode*>::iterator v = openList.begin();
     
    
     for(;v!=openList.end();++v){
        if(*v==node){
           openList.erase(v);
            break;
        }
        
    }
 
    closeList.push_back(node);
}


void MyAStar::Init(int* data , int w,int h){
    col=h;
    row=w;
    astarMapArr.clear();
    for(uint32 i=0;i<h;i++){
        vector<AStarNode> cols; 
        astarMapArr.push_back(cols);
        for(int j=0;j<w;j++){
            AStarNode node(j,i,data[i*row+j] );
            astarMapArr[i].push_back(node);  
            
        }
         
    }
}

 

void MyAStar::nodeLogic(AStarNode* node, AStarNode* centerNode, int addG){
    
    if(node->inList!=2){										//如果其不在关闭列表中。
        if(node->inList==0){									//也不在开启列表中。
            node->inList = 1;								//记录其在开启列表中。
            node->parentNode = centerNode;					//记录其父层对象。
            node->g = centerNode->g+addG;						//计算出其 G 值。
            node->h = 0;							//计算出其 H 值。
            node->f = node->g+node->h;							//算出其 F 值。
            openList.push_back(node);							//添加其到开启列表。 
        }else{												//如果在开启列表中。
            int g = centerNode->g+addG;					//计算出其新的 G 值。
            if(g < node->g){									//如果新的 G 值小于原先的，说明这条路径更短。
                node->g = g;									//计算出其新的 G 值。
                node->f = node->g+node->h;						//算出其新的 F 值。
                nowNode = node->parentNode;					//把这一格的父节点改成当前节点。
            }
        }
    }
    
    
}


void MyAStar::getAroundNode(AStarNode* centerNode, bool aspect){
    int now_x = centerNode->x;
    int now_y = centerNode->y;
    AStarNode* t=NULL;
    //记录上下左右四个邻近节点是否可以到达，用于综合其他方向判断斜向的节点。
    bool go_up=false, go_down=false, go_left=false, go_right=false;
    //先获取上下左右四个邻近节点。
    if(now_y>0){											//上方还有节点。
        //如果是偶数
        if(now_y % 2 == 0){
            if(now_x<row-1){
                t = &astarMapArr[now_y-1][now_x+1];
            }
        }else{
            t = &astarMapArr[now_y-1][now_x];
        }
        //t = astarMapArr[now_y-1][now_x];					//获取上方的节点。
        if(t){
            if(t->type==0){										//此节点可通过。
                go_up = true;									//记录上方可行，用于综合其他方向判断斜向的节点。
                nodeLogic(t, centerNode, 10);
            }
        }
    }
    if(now_y<col-1){
        //如果是偶数
        if(now_y % 2 == 0){
            t = &astarMapArr[now_y+1][now_x];
        }else{
            if(now_x>0){
                t = &astarMapArr[now_y+1][now_x-1];
            }
        }
        //t = astarMapArr[now_y+1][now_x];
        if(t){
            if(t->type==0){
                go_down = true;
                nodeLogic(t, centerNode, 10);
            }
        }
    }
    if(now_y>0){
        //如果是偶数	,	左方向
        if(now_y % 2 == 0){
            t = &astarMapArr[now_y-1][now_x];
        }else{
            if(now_x>0){
                t = &astarMapArr[now_y-1][now_x-1];
            }
        }
        //t = astarMapArr[now_y][now_x-1];
        if(t){
            if(t->type==0){
                go_left = true;
                nodeLogic(t, centerNode, 10);
            }
        }
    }
    if(now_y<col-1){
        //如果是偶数 ,	右方向
        if(now_y % 2 == 0){
            if(now_x<row-1){
                t = &astarMapArr[now_y+1][now_x+1];
            }
        }else{
            t = &astarMapArr[now_y+1][now_x];
        }
        //t = astarMapArr[now_y][now_x+1];
        if(t){
            if(t->type==0){
                go_right = true;
                nodeLogic(t, centerNode, 10);
            }
        }
    }
    //如果为搜寻八方向则获取斜向的四个节点，否则不搜寻。
    if(aspect){
        if(go_up && go_left){
            if(now_y>1){
                t = &astarMapArr[now_y-2][now_x];		//ok , nw
            }
            if(t){
                if(t->type==0)
                    nodeLogic(t, centerNode, 14);
            }
        }
        if(go_up && go_right){
            if(now_x<row-1){
                t = &astarMapArr[now_y][now_x+1];		//ok , ne
            }
            if(t){
                if(t->type==0)
                    nodeLogic(t, centerNode, 14);
            }
        }
        if(go_down && go_left){
            if(now_x>0){
                t = &astarMapArr[now_y][now_x-1];		//ok , sw
            }
            if(t){
                if(t->type==0)
                    nodeLogic(t, centerNode, 14);
            }
        }
        if(go_down && go_right){
            if(now_y<col-2){
                t = &astarMapArr[now_y+2][now_x];		//ok , se
            }
            if(t){
                if(t->type==0)
                    nodeLogic(t, centerNode, 14);
            }
        }
    }
}

int MyAStar::getBlock(int nX,int nY){
    if(nY<0 ||nY>=col ){
        return 1;
    }
    
    if(nX<0 ||nX>=row ){
        return 1;
    }
    
    return astarMapArr[nY][nX].type;
}

bool MyAStar::isBlock(int nX,int nY){
    return getBlock(nX,nY)==1;
}

void MyAStar::reset(){
    openList.clear();
    closeList.clear();
    
    for (int i=0;i<col;i++){
        for (int j=0;j<row;j++){
            astarMapArr[i][j].reset();
        }
    }
}


void MyAStar::cleanUp(){
    startNode = NULL;
    endNode = NULL;
    openList.clear();
    closeList.clear();
    astarMapArr.clear();
}

